package org.java.admin.utils;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;

import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

/**
 * 封装RedisUtils基础操作
 * @Author  css
 * @Date 2020-7-18
 */
@Component
public class RedisUtils {

    //实现对Redis的基础的操作
    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    //============================common==================================
    /**
     * 指定缓存失效时间
     * @param key
     * @param time
     * @return
     */
    public boolean expire(String key, long time) {
        try {
            if(time >0){
                redisTemplate.expire(key, time, TimeUnit.SECONDS);
            }
            return true;
        }catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 根据key获取过期时间
     * @param key
     * @return
     */
    public long getExpire(String key) {
        return redisTemplate.getExpire(key, TimeUnit.SECONDS);
    }

    /**
     * 判断key是否存在
     * @param key
     * @return
     */
    public boolean hasKey(String key) {
        try {
            return redisTemplate.hasKey(key);
        } catch (Exception e) {e.printStackTrace();}
            return false;
        }

    //============================String==================================
    /**
     * 普通缓存对的存放
     * @param key
     * @param object
     * @return true 成功 ? false 失败
     */
    public boolean set(String key, Object object) {
        try {
            redisTemplate.opsForValue().set(key, object);
            return true;
        }catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 普通缓存的获取
     * @param key
     * @return 值
     */
    public Object get(String key) {
        return key == null ? null : redisTemplate.opsForValue().get(key);
    }

    /**
     * 普通缓存的放入并设置失效时间
     * @param key
     * @param object
     * @param time
     * @return true成功?false失败
     */
    public boolean set(String key, Object object, long time) {
        try {
            if (time >0) {
                redisTemplate.opsForValue().set(key, object, time);
            } else {
                set(key, object);
            }
            return true;
        }catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 递增
     * @param key
     * @param delta
     * @return
     */
    public long incr(String key, long  delta) {
        if (delta < 0){
            throw new RuntimeException("递增因子必须大于0");
        }
        return redisTemplate.opsForValue().increment(key, delta);
    }

    /**
     * 递减
     * @param key
     * @param delta
     * @return
     */
    public long decr(String key, long delta) {
        if (delta < 0) {
            throw new RuntimeException("递减因子必须大于0");
        }
       return redisTemplate.opsForValue().increment(key, -delta);
    }

    //============================Map==================================

    /**
     * 存放 hash
     * @param key
     * @param map
     * @return true 成功 ？ false 失败
     */
    public boolean hmSet(String key, Map<String, Object> map) {
        try {
            redisTemplate.opsForHash().putAll(key, map);
            return true;
        }catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获取 hash
     * @param key
     * @param item
     * @return 值
     */
    public Object hGet(String key, String item) {
        return redisTemplate.opsForHash().get(key, item);
    }

    /**
     * 获取hashKey的所有键值
     * @param key
     * @return
     */
    public Map<Object, Object> hmGet(String key) {
      return redisTemplate.opsForHash().entries(key);
    }

    /**
     * 存放Hash  并设置过期时间
     * @param key
     * @param map
     * @param time
     * @return
     */
    public boolean hmSet(String key, Map<String ,Object> map, long time) {
        try {
            if (time < 0) {
                redisTemplate.opsForHash().putAll(key, map);
            }
            expire(key, time);
            return true;
        }catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 删除Hash表中的值
     * @param key 不能为空
     * @param item  可以是多个，不能为空
     */
    public void hDel(String key, Object item) {
        redisTemplate.opsForHash().delete(key, item);
    }

    /**
     * 判断 Hash表中是否有该项值
     * @param key 不能为空
     * @param item 不能为空
     * @return true 成功 ? false失败
     */
    public boolean hHasKey(String key, String item) {
        return redisTemplate.opsForHash().hasKey(key, item);
    }

    /**
     * Hash 递增
     * @param key 键不能为空
     * @param item 值不能为空
     * @param by 要增加几（大于0）
     * @return
     */
    public double hinCr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, by);
    }

    /**
     * Hash 递减
     * @param key 键不能为空
     * @param item 值不能为空
     * @param by 要减到几(小于0)
     * @return
     */
    public double hdeCr(String key, String item, double by) {
        return redisTemplate.opsForHash().increment(key, item, -by);
    }

    //============================Set==================================

    /**
     * 将数据放到Set缓存中
     * @param key 键
     * @param value 值 可以为多个
     * @return 返回成功个数
     */
    public long sSet(String key, Object value) {
        try {
            return redisTemplate.opsForSet().add(key, value);
        }catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 根据key获取Set中所有的值
     * @param key
     * @return Set的值的集合
     */
    public Set<Object> sGet(String key) {
        try {
            return redisTemplate.opsForSet().members(key);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 根据value，key。去查询Set中是否存在
     * @param key
     * @param value
     * @return
     */
    public boolean sHasKey(String key, Object value) {
        return redisTemplate.opsForSet().isMember(key, value);
    }

    /**
     *  存放数据到Set缓存中去
     * @param key 键
     * @param value 值
     * @param time 过期时间
     * @return 成功个数
     */
    public long sSetAndTime(String key, Object value, long time) {
        try {
            Long count = redisTemplate.opsForSet().add(key, value);
            if (time > 0) {
                expire(key, time);// 设置过期时间
            }
            return count;
        }catch (Exception e) {
            e.printStackTrace();
            return 0;
        }
    }

    /**
     * 获取Set的缓存长度
     * @param key 键
     * @return Set的长度
     */
    public long getSetSize(String key) {
        return redisTemplate.opsForSet().size(key);
    }

    /**
     * 根据key移除 values
     * @param key 键
     * @param values 值 可以是多个
     * @return 移除的个数
     */
    public long removeSet(String key, Object values) {
        return redisTemplate.opsForSet().remove(key, values);
    }

    //============================List==================================

    /**
     * 将单个对象放入List中缓存到Redis中
     * @param key
     * @param value
     * @return
     */
    public boolean lSet(String key, Object value) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            return true;
        }catch (Exception e) {
            e.printStackTrace();
            return false;
        }
    }

    /**
     * 获取List的缓存内容
     * @param key
     * @param start
     * @param end
     * @return
     */
    public List<Object> lGet(String key, long start, long end) {
        return redisTemplate.opsForList().range(key, start, end);
    }

    /**
     * 获取List缓存的长度
     * @param key
     * @return
     */
    public long lGetListSize(String key) {
        try {
            return redisTemplate.opsForList().size(key);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }

    /**
     * 通过索引获取List中的值
     * @param key
     * @param index
     * @return
     */
    public Object lGetIndex(String key, long index) {
        try {
            return redisTemplate.opsForList().index(key, index);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 把单个对象List放入缓存中并设置过期时间
     * @param key
     * @param value
     * @param time
     * @return
     */
    public boolean lSet(String key, Object value, long time) {
        try {
            redisTemplate.opsForList().rightPush(key, value);
            if (time > 0) {
                expire(key, time); //设置过期时间
                return true;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /***
     * 将多个对象放入List中缓存到Redis中并设置过期时间
     * @param key
     * @param value
     * @param time
     * @return
     */
    public boolean lSet(String key, List<Object> value, long time) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            if (time > 0) {
                expire(key, time);
            }
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     *  将多个对象放入List中缓存到Redis中
     * @param key
     * @param value
     * @return
     */
    public boolean lSet(String key, List<Object> value) {
        try {
            redisTemplate.opsForList().rightPushAll(key, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 根据索引修改List中的某条数据
     * @param key
     * @param index
     * @param value
     * @return
     */
    public boolean lUpdateIndex(String key, long index, Object value) {
        try {
            redisTemplate.opsForList().set(key, index, value);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 移除N个值为value
     * @param key
     * @param count
     * @param value
     * @return
     */
    public long lRemove(String key, long count, Object value) {
        try {
            return redisTemplate.opsForList().remove(key, count, value);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return 0;
    }
}
